package com.mebs.web;

import com.ibm.icu.text.DateFormatSymbols;
import com.ibm.icu.util.Calendar;
import com.mebs.model.WeightUnit;
import com.mebs.model.inventory.Confirmation;
import com.mebs.model.inventory.ConfirmationItem;
import com.mebs.model.reports.lags.FixedStatusLagsReport;
import com.mebs.model.util.Month;
import org.jt.jet.JetContext;
import org.jt.jet.util.JetUtils;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * MEBSUtils
 */
public class MEBSUtils extends JetUtils {

	public static final MEBSUtils INSTANCE = new MEBSUtils();

	public static final Pattern EMAIL_PATTERN = Pattern.compile("(\\w+)@(\\w+\\.)(\\w+)(\\.\\w+)*");

	public static final String datePatern = "MM/dd/yyyy";
	public static final String timePatern = "mm:hh";

	public static Month[] getMonths(final int year, final Locale locale) {
		Calendar calendar = Calendar.getInstance(locale);
		calendar.set(Calendar.YEAR, year);
		DateFormatSymbols symbols = new DateFormatSymbols(calendar, locale);
		int maxMonth = calendar.getActualMaximum(Calendar.MONTH);
		Month[] months = new Month[maxMonth + 1];
		String[] monthNames = symbols.getMonths(DateFormatSymbols.STANDALONE, DateFormatSymbols.WIDE);
		String[] shortMonths = symbols.getShortMonths();
		for (int i = 0; i < monthNames.length && i <= maxMonth; i++) {
			months[i] = new Month(calendar, i + 1, monthNames[i], shortMonths[i]);
		}
		return months;
	}

	public static String getPlusMinusString(String val) {
		if (val != null) {
			try {
				Double num = NumberFormat.getNumberInstance().parse(val).doubleValue();
				if (num > 0) {
					val = "+" + val;
				} else if (num < 0) {
					val = "-" + val;
				} else {
					val = "0";
				}
			} catch (ParseException ex) {
				val = "0";
			}
		}

		return val;
	}

	public static String getIString(Integer value) {
		return value == null ? "" : value.toString();
	}

	public static String getPlusMinusString(int val) {
		String str = "0";

		if (val > 0) {
			str = "+" + Integer.toString(val);
		} else if (val < 0) {
			str = Integer.toString(val);
		}

		return str;
	}

	public static String getPlusMinusString(double val) {
		String str = "0";

		if (val > 0) {
			str = "+" + Double.toString(val);
		} else if (val < 0) {
			str = Double.toString(val);
		}

		return str;
	}

	public static String formatDate(Date date) {
		if (date == null) return "";
		JetContext jetContext = JetContext.getThreadInstance();
		return jetContext == null ?
				DateFormat.getDateInstance(DateFormat.SHORT).format(date) :
				jetContext.getApplication().getConfiguration().getDefaultDateFormat().format(date);
	}
	
	public static String valueOrNA(String s) {
		if (s == null || s.length() == 0) {
			return "N/A";
		} else {
			return s;
		}
	}
	
	public static String valueOrEmpty(Object o) {
		if (o == null) {
			return "";
		} else {
			return String.valueOf(o);
		}
	}

	public static String getYesNoString(Boolean value) {
		if (value == null || !value.booleanValue()) {
			return "No";
		} else {
			return "Yes";
		}
	}

	public static String getStringPortion(String str) {
		return getStringPortion(str, 50);
	}

	public static String getStringPortion(String str, int portionSize) {
		if (str == null) {
			return "";
		}

		StringBuilder sb = new StringBuilder(str);
		if (sb.indexOf(".") >= 0 && sb.indexOf(".") < portionSize) {
			int prevLength = sb.length();
			sb.replace(0, sb.length(), sb.substring(0, sb.indexOf(".") + 1));
			if (sb.length() < prevLength) {
				sb.append("..");
			}
		} else {
			if (sb.length() >= portionSize) {
				int spacePos = sb.indexOf(" ", portionSize);
				if (spacePos < 0) {
					spacePos = portionSize;
				}
				sb.replace(0, sb.length(), sb.substring(0, spacePos));
				sb.append("...");
			}
		}
		return sb.toString();
	}

	public static Double dot2f(Double v) {
		return Math.floor(v * 100) / 100;
	}

	public static String get2FractionDigitsNumber(Double number) {
		if (number == null) {
			return "";
		}

		NumberFormat nf = NumberFormat.getInstance();
		nf.setMaximumFractionDigits(2);
		nf.setMinimumFractionDigits(2);

		return nf.format(number).replace(",", "");
	}

	public static String formatPrice(Double price) {
		return get2FractionDigitsNumber(price);
	}

	public static String[] getStrings(String multiLineStr) {
		String lineSeparator = System.getProperty("line.separator", "\n");
		multiLineStr = multiLineStr.replace("$", lineSeparator);

		return multiLineStr.split(lineSeparator);
	}

	public static String formatToFiveZero(Integer mNumber) {
		String result = String.valueOf(mNumber);
		switch (result.length()) {
			case 1:
				result = "0000" + mNumber;
				break;
			case 2:
				result = "000" + mNumber;
				break;
			case 3:
				result = "00" + mNumber;
				break;
			case 4:
				result = "0" + mNumber;
				break;
		}

		return result;
	}

        public static String formatPallet(String mNumber) {
                return mNumber == null ? "" : mNumber;
	}

	public static int getDayOfYear(Date date) {
		java.util.Calendar cal = java.util.Calendar.getInstance();
		cal.setTime(date);
		return cal.get(java.util.Calendar.DAY_OF_YEAR);
	}

	public static int getAvrNumberOfItemPerRC(List<Confirmation> confirmationList) {
		int sum = 0;
		int count = 0;
		for (Confirmation c : confirmationList) {
			for (ConfirmationItem ci : c.getItems()) {
				sum = +ci.getQuantityReceived();
				count++;
			}
		}
		return count == 0 ? 0 : Math.round(sum / count);
	}

	public static int getAvrDaysReceivedToDelivered(List<FixedStatusLagsReport> fixedReport) {
		int sum = 0;
		int count = 0;
		for (FixedStatusLagsReport repLine : fixedReport) {
			sum += repLine.getReceivedToDelivered();
			count++;
		}
		return count == 0 ? 0 : Math.round(sum / count);
	}

	public static int getAvrDaysReceivedToOnHand(List<FixedStatusLagsReport> fixedReport) {
		int sum = 0;
		int count = 0;
		for (FixedStatusLagsReport repLine : fixedReport) {
			sum += repLine.getReceivedToOnhand();
			count++;
		}
		return count == 0 ? 0 : Math.round(sum / count);
	}

	public static int getAvrDaysOnHandToInTransit(List<FixedStatusLagsReport> fixedReport) {
		int sum = 0;
		int count = 0;
		for (FixedStatusLagsReport repLine : fixedReport) {
			sum += repLine.getOnHandToInTransit();
			count++;
		}
		return count == 0 ? 0 : Math.round(sum / count);
	}

	public static int getAvrDaysReceivedToInTransit(List<FixedStatusLagsReport> fixedReport) {
		int sum = 0;
		int count = 0;
		for (FixedStatusLagsReport repLine : fixedReport) {
			sum += repLine.getReceivedToInTransit();
			count++;
		}
		return count == 0 ? 0 : Math.round(sum / count);
	}

	public static int getLagForDates(Date dateFrom, Date dateTo) {
		if (dateFrom == null || dateTo == null)
			return 0;
		else
			return getDayOfYear(dateTo) - getDayOfYear(dateFrom);
	}

	public static Date getFirstDayOfMonth() {
		java.util.Calendar cal = java.util.Calendar.getInstance();
		cal.setTime(new Date());
		cal.set(java.util.Calendar.DAY_OF_MONTH, 1);
		return cal.getTime();
	}

	public static Date getLastDayOfMonth() {
		java.util.Calendar cal = java.util.Calendar.getInstance();
		cal.setTime(new Date());
		int lastDate = cal.getActualMaximum(Calendar.DATE);
		cal.set(Calendar.DATE, lastDate);
		return cal.getTime();
	}

	public static boolean isDateInRange(Date checkDate, Date dateFrom, Date dateTo) {
		if (dateFrom == null) return true;
		if (dateTo == null) return true;
		return checkDate.getTime() > dateFrom.getTime() && checkDate.getTime() <= dateTo.getTime();
	}

	public static boolean checkChecboxes(boolean hazmat, boolean crated, boolean consolidated, Boolean hazmat1, Boolean crated1, Boolean consolidated1) {
		boolean result1,result2,result3;
		if (hazmat) {
			result1 = hazmat == hazmat1;
			if (!result1) return false;
		}
		if (crated) {
			result2 = crated == crated1;
			if(!result2) return false;
		}
		if (consolidated) {
			result3 = consolidated == consolidated1;
			if(!result3) return false;
		}

		return true;
	}
	
	/**
	 * Returns a subset of the original set. 
	 * If the original set size is less than or equals to the specified size, the original set is returned
	 * 
	 * @param originalSet
	 * @param maxSize - size of the returned subSet
	 * @author nit
	 */
	public static Set getSubset(Set originalSet, int maxSize) {
		if (originalSet.size() <= maxSize) {
			return originalSet;
		}
		
		List boxItemsSublist = new ArrayList();
		Collections.addAll(boxItemsSublist, originalSet.toArray());
		boxItemsSublist = boxItemsSublist.subList(0, maxSize);
		
		Set boxItemsSubset = new HashSet();
		boxItemsSubset.addAll(boxItemsSublist);
		
		return boxItemsSubset;
	}
	
	/**
	 * Returns a substring of the original string, which is no longer than the specified amount of characters.
	 * Ellipsis ('...') will be added to the end of the string if it has been truncated
	 * 
	 * @param originalString
	 * @param maxLength - maximum length of the returned String
	 * @author nit
	 */
	public static String limitString(String originalString, int maxLength) {
		if (originalString == null) {
			return "";
		} else if (originalString.length() <= maxLength) {
			return originalString;
		} else {
			return originalString.substring(0, maxLength-3).concat("...");
		}
	}
	
	public static String getWeightUnitLabel(int weightUnitType) {
		return WeightUnit
			.getObjectByType(weightUnitType)
			.getShortName();
	}
}
